package com.ning.city.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ning.city.bean.Info;
import com.ning.city.bean.InfoType;
import com.ning.city.dto.InfoDto;
import com.ning.city.mapper.InfoMapper;
import com.ning.city.mapper.InfoTypeMapper;
import com.ning.city.vo.PageData;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDate;
import java.util.*;

/**
 * @author Ning 242741154@qq.com
 * @date 2021/1/7 13:58
 */
@Service
public class InfoService {
    private final InfoMapper infoMapper;
    private final InfoTypeMapper infoTypeMapper;
    private final RedisTemplate<String, String> redisTemplate;

    public InfoService(InfoMapper infoMapper, InfoTypeMapper infoTypeMapper, RedisTemplate<String, String> redisTemplate) {
        this.infoMapper = infoMapper;
        this.infoTypeMapper = infoTypeMapper;
        this.redisTemplate = redisTemplate;
    }

    private static final String INFO_PAID_REDIS_PREFIX = "paid-";
    private static final Duration RECOMMEND_DURATION
            = Duration.ofDays(2);

    /**
     * 添加信息
     *
     * @param dto InfoDto.Add
     * @return 是否成功
     */
    public boolean add(InfoDto.Add dto) {
        final Info info = new Info();
        info.setType(dto.getType());
        info.setTitle(dto.getTitle());
        info.setLinkman(dto.getLinkman());
        info.setPhone(dto.getPhone());
        info.setContent(dto.getContent());
        info.setEmail(dto.getEmail());
        info.setDate(LocalDate.now());
        return infoMapper.insert(info) == 1;
    }

    /**
     * 获取全部 InfoType 数据
     *
     * @return InfoType 数据
     */
    public List<InfoType> getAllTypes() {
        return infoTypeMapper.selectList(null);
    }

    /**
     * 获取 Info 数量
     *
     * @return Info 数量
     */
    public Integer getCount() {
        return infoMapper.selectCount(null);
    }

    /**
     * 获取 Info 的分页数据
     *
     * @param pageInfo 分页信息
     * @return 页面数据
     */
    public PageData<Info> getPageData(InfoDto.PageInfo pageInfo) {
        PageData<Info> pageData = new PageData<>();
        pageData.setPageInfo(pageInfo);
        pageData.setCount(getCount());
        QueryWrapper<Info> query = new QueryWrapper<>();
        // 根据类型查找
        Integer infoType = pageInfo.getInfoType();
        query.eq(infoType != null && infoType != 0,
                "type", infoType);
        // 根据关键字查找
        String keyword = pageInfo.getKeyword();
        query.like(keyword != null && !keyword.equals(""),
                "content", keyword);
        // 分页信息
        int pageNum = pageInfo.getPageNum();
        int pageSize = pageInfo.getPageSize();
        query.last("limit "
                + (pageNum - 1) * pageSize + "," + pageSize);
        // 执行查询
        List<Info> infos = infoMapper.selectList(query);
        pageData.setData(infos);
        return pageData;
    }

    /**
     * 为 info 付费
     *
     * @param infoId infoId
     * @return 是否成功
     */
    public boolean pay4(String infoId) {
        Info info = new Info();
        info.setId(infoId);
        info.setPayFor("已支付");
        boolean b = infoMapper.updateById(info) == 1;
        if (!b) {
            return false;
        }
        redisTemplate.opsForValue().set(INFO_PAID_REDIS_PREFIX + infoId,
                infoId, RECOMMEND_DURATION);
        return true;
    }

    /**
     * 获取推荐列表
     * <p>
     * 在已付费的 info 中随机选取 5 条推荐到首页
     * </p>
     *
     * @return recommend infos
     */
    public List<Info> getRecommendInfos() {
        Set<String> keys = redisTemplate.keys(INFO_PAID_REDIS_PREFIX + "*");
        if (keys == null || keys.size() == 0) {
            return new ArrayList<>();
        }
        QueryWrapper<Info> query = new QueryWrapper<>();
        if (keys.size() <= 5) {
            query.in("id", keys);
        } else {
            ArrayList<String> arr = new ArrayList<>(keys);
            ArrayList<String> arr2 = new ArrayList<>();
            Random random = new Random();
            while (arr2.size() < 5) {
                arr2.add(arr.get(random.nextInt(arr.size())));
            }
            query.in("id", arr2);
        }
        return infoMapper.selectList(query);
    }
}
